#ifndef XFUNCTION_HPP
#define XFUNCTION_HPP

#include <iostream>
#include<memory>
#include<future>
template<typename>
class functorImpl;

template<typename result,typename...Args>
class functorImpl<result(Args...)>{
public:
    virtual result operator()(Args...)=0;
    virtual result operator()(void*,Args...){}; 
    virtual result operator()(std::promise<void>*,Args...){};
    virtual ~functorImpl(){}
};

//仿函数和普通函数functorHanlder
template<typename Fun,typename result,typename ...Args>
class functorHanlder:public functorImpl<result(Args...)>
{
public:
    functorHanlder(const Fun& fun):m_fun(fun){}
    result operator ()(Args... args ){
        return m_fun(args...);
    }

    result operator ()(std::promise<void>*p,Args... args ){
        m_fun(args...);
        if(p) p->set_value();
        return;
    }
private:
    Fun m_fun;
};

//成员函数MemFunHanlder接受智能指针weak_ptr
template<typename destClass,typename pointerToMemFn,typename result,typename ...Args>
class MemFunHanlder;

template<typename destClass,typename pointerToMemFn,typename result,typename ...Args>
class MemFunHanlder<std::weak_ptr<destClass>,pointerToMemFn,result,Args...>:public functorImpl<result(Args...)>
{
public:
    MemFunHanlder(std::weak_ptr<destClass> pobj,pointerToMemFn pMemFn):m_pObj(pobj),m_pMemFn(pMemFn){}
    
    result operator() (Args...args){
        //此时需要判断指针的失效问题
        auto sharePtr = m_pObj.lock();
        if(sharePtr){
            return ( (*sharePtr).*m_pMemFn )(args...);
        }else{
            std::cout<<"接收者指针已失效"<<std::endl;
            return;
        }
    }

    result operator ()(std::promise<void>*p,Args... args ){
         auto sharePtr = m_pObj.lock();
        if(sharePtr){
            ( (*sharePtr).*m_pMemFn )(args...);
            if(p) p->set_value();
        }else{
            std::cout<<"接收者指针已失效"<<std::endl;
            if(p) p->set_value();
        }
        return;
    }
private:
    std::weak_ptr<destClass> m_pObj;
    pointerToMemFn m_pMemFn;
};

//成员函数MemFunHanlder接受智能指针share_ptr
template<typename destClass,typename pointerToMemFn,typename result,typename ...Args>
class MemFunHanlder<std::shared_ptr<destClass>,pointerToMemFn,result,Args...>:public functorImpl<result(Args...)>
{
public:
    MemFunHanlder(std::shared_ptr<destClass> pobj,pointerToMemFn pMemFn):m_pObj(pobj),m_pMemFn(pMemFn){}
    
    result operator() (Args...args){
        //此时需要判断指针的失效问题
        auto sharePtr = m_pObj.lock();
        if(sharePtr){
            return ( (*sharePtr).*m_pMemFn )(args...);
        }else{
            std::cout<<"接收者指针已失效"<<std::endl;
            return;
        }
    }

    result operator() (std::promise<void>*p,Args... args){
        //此时需要判断指针的失效问题
        auto sharePtr = m_pObj.lock();
        if(sharePtr){
             ( (*sharePtr).*m_pMemFn )(args...);
             if(p) p->set_value();
        }else{
            std::cout<<"接收者指针已失效"<<std::endl;
            if(p) p->set_value();
        }
        return;
    }
private:
    std::weak_ptr <destClass> m_pObj;
    pointerToMemFn m_pMemFn;
};

//成员函数MemFunHanlder
template<typename destClass,typename pointerToMemFn,typename result,typename ...Args>
class MemFunHanlder<destClass*,pointerToMemFn,result,Args...>:public functorImpl<result(Args...)>
{
public:
    MemFunHanlder(destClass* pobj,pointerToMemFn pMemFn):m_pObj(pobj),m_pMemFn(pMemFn){}
    result operator() (Args...args){
        return  ( (*m_pObj).*m_pMemFn )(args...);
    }

    result operator() (void* pobj,Args...args){
        destClass* p = (destClass*)(pobj);
        return  ( (*p).*m_pMemFn )(args...);
    }

    result operator() (std::promise<void>* xpromise,Args...args){
        ( (*m_pObj).*m_pMemFn )(args...);
        if(xpromise) xpromise->set_value();
        return;
    }

private:
    destClass* m_pObj;
    pointerToMemFn m_pMemFn;
};

//functional 利用的是装饰器模式或者代理模式的设计思路
template <class _Ty>
struct xIs_memfunptr;

template <class _Ret, class _Arg0, class... _Types>                                   
    struct xIs_memfunptr<_Ret ( _Arg0::*)(_Types...)> {                                      
        using  Class_type = _Arg0;                                                   
    };

template<typename>
class xfunction;

template<typename result,typename ...Args>
class xfunction<result(Args...)>:public functorImpl<result(Args...)>{
public:
    typedef functorImpl<result(Args...)> baseType;
public:
    xfunction() = default;
    template<typename Fun>
    xfunction(Fun fun){
        if constexpr(std::is_member_function_pointer_v<Fun>){
            using Class_type = typename xIs_memfunptr<Fun>::Class_type;
            pshareFun.reset(new MemFunHanlder<Class_type*,Fun,result,Args...>(nullptr,fun));  
        }else
            pshareFun.reset(new functorHanlder<Fun,result,Args...>(fun));
    }

    //接受函数对象和全局函数指针
    template<typename pointerToObj,typename pointerToMemFn>
     xfunction(pointerToObj pobj,pointerToMemFn pMemFn){
         pshareFun.reset(new MemFunHanlder<pointerToObj,pointerToMemFn,result,Args...>(pobj,pMemFn));
     }

    //接受weak_ptr
     template<typename destClass,typename pointerToMemFn>
     xfunction(std::weak_ptr<destClass> pobj,pointerToMemFn pMemFn){
         pshareFun.reset(new MemFunHanlder<std::weak_ptr<destClass>,pointerToMemFn,result,Args...>(pobj,pMemFn));
     }

    //接受share_ptr
     template<typename destClass,typename pointerToMemFn>
     xfunction(std::shared_ptr<destClass> pobj,pointerToMemFn pMemFn){
         pshareFun.reset(new MemFunHanlder<std::shared_ptr<destClass>,pointerToMemFn,result,Args...>(pobj,pMemFn));
     }

    //调用
    result operator ()(Args... args ){
        if(pshareFun)
            return (*pshareFun)(args...);
        else
            return result();
    }

    template<typename...types>
    result operator ()(types... args ){
        if(pshareFun)
            return (*pshareFun)(args...);
        else
            return result();
    }
private:
    std::shared_ptr<functorImpl<result(Args...)>> pshareFun;        //使用智能指针避免内存泄露，同事避免深层拷贝浪费资源
};
#endif